#pragma once

#define HEARTBEAT_INTERVAL	30000

class CWebWsConn;
class CWebSocketConn;

typedef void (*WSONMSGCALLBACK)(LPCTSTR lpszMsg);
typedef void (*WSONRECONNECTED)(CWebWsConn* pConn);


CStringA T2UTF8(const CString& csStr);
CString UTF82T(const CStringA& csStr);
CStringA T2UTF8(LPCTSTR lpszStr);
CString UTF82T(LPCSTR lpszStr);
CString UrlEncode(LPCTSTR lpszStr);
CString UrlDecode(LPCTSTR lpszStr);

class CWebWsConn
{
public:
	CWebWsConn(void);
	~CWebWsConn(void);

public:
	BOOL WsConnect(LPCTSTR lpszWsUrl, WSONMSGCALLBACK pOnMsgCallBackFunc, WSONRECONNECTED pOnReconnectedCallBackFunc);
	void WsDisconnect();
	void WsReconnect();
	BOOL WsSend(LPCTSTR lpszMsg);

	friend DWORD CALLBACK ThreadHeartBeat(LPVOID lpParam);
	friend DWORD CALLBACK ThreadDoReconnect(LPVOID lpParam);

private:
	void WsStartHeartBeat();
	void WsStopHeartBeat();

private:
	HANDLE m_hHeartBeatThread;
	BOOL m_bStopHeartBeat;
	BOOL m_bReconnecting;
	BOOL m_bFirstTry;
	CWebSocketConn* m_pWebSocketConn;
	CString m_csWsUrl;
	WSONMSGCALLBACK m_pOnMsgCallBackFunc;
	WSONRECONNECTED m_pOnReconnectedCallBackFunc;
};

class CWebHttpConn
{
public:
	CWebHttpConn(void)
	{
		m_HttpSession.SetOption(INTERNET_OPTION_CONNECT_TIMEOUT, 1000 * 30);
		m_HttpSession.SetOption(INTERNET_OPTION_CONNECT_RETRIES, 3);
	}
	~CWebHttpConn(void){}

public:
	BOOL HttpSetHost(LPCTSTR lpszHttpHostname, WORD wPort=80);
	void HttpSetHeader(LPCTSTR lpszHeaders);
	const CString& HttpGetHeader();
	void HttpAddHeader(LPCTSTR lpszHeaders);
	BOOL HttpGetString(LPCTSTR lpszUri, CString& csRet);
	BOOL HttpGetToFile(LPCTSTR lpszUri, LPCTSTR lpszFilePathName);
	BOOL HttpPostString(LPCTSTR lpszUri, LPCTSTR lpszPostData, CString& csRet);
	BOOL HttpPostFile(LPCTSTR lpszUri, LPCTSTR lpszFieldName, LPCTSTR lpszFilePathName, LPCTSTR lpszRemoteFileName, CString& csRet);

private:
	BOOL SecurityRandom(LPVOID lpBuffer, DWORD dwLen) const;
	CString GenerateBoundary() const;
	CStringA MakePreFileData(LPCTSTR lpszBoundary, LPCTSTR lpszFieldName, LPCTSTR lpszFileName) const;
	CStringA MakePostFileData(LPCTSTR lpszBoundary) const;

public:
	CInternetSession m_HttpSession;
	CString m_csHostname;
	INTERNET_PORT m_Port;
	CString m_csHttpHeaders;
};

class CWebConn : public CWebWsConn, public CWebHttpConn
{
};